#include "Polinomio.h"
#include <vector>
#include <algorithm>
double * Polinomio::getCoefs(){
	return coef;
	}


static bool Cero (double x)

    {

    const double cero = 1e-20;

    return (x <= cero);

    }


inline bool Polinomio::Nulo() const

    {

    return ((grado == 0) && Cero(coef[0]));

    }


Polinomio::Polinomio()

    {

    coef = new double[1];

    assert(coef != 0);

    coef[0] = 0;

    grado = 0;

    }


Polinomio::Polinomio(double * Coef, int Grado)

    {

    grado = Grado;

    coef = new double[grado + 1];

    assert(coef != 0);

    for (int i = 0; i <= grado; i++)

         coef[i] = Coef[i];

    }


Polinomio::Polinomio(const Polinomio & p)

    {

    grado = p.grado;

    coef = new double[grado];

    assert(coef != 0);

    for (int i = 0; i <= grado; i++)

         coef[i] = p.coef[i];

    }


double Polinomio::Coef(int i) const

    {

    assert (0 <= i);

     if (i > grado)

        return 0;

     return coef[i];

     }


inline int Polinomio::Grado() const

    {

    return grado;

   }


double Polinomio::operator()(double x) const

    {

    double suma = 0;

    for (int i = grado; i > 0; i--)

         suma = x * (coef[i] + suma);

    suma += coef[0];

    return suma;

    }


Polinomio & Polinomio::operator=(const Polinomio & p)

     {

     if (&p == this)

        return *this;

     if (grado == p.grado)

        {

        for (int i = 0; i <= grado; i++)

             coef[i] = p.coef[i];

        return *this;

        }

     grado = p.grado;

     //delete [] coef;

     coef = new double[p.grado + 1];

     for (int i = 0; i <= grado; i++)

           coef[i] = p.coef[i];

     return *this;

     }


bool Polinomio::operator==(const Polinomio & p) const

    {

    if (grado != p. grado)

       return false;

    int i = grado;

    while ((coef[i] == p.coef[i]) && i >= 0)

              i--;

    return (i < 0);

    }


inline bool Polinomio::operator!=(const Polinomio & p) const

    {

    return !(*this == p);

    }


Polinomio & operator-(Polinomio & p)

    {

    for (int i = 0; i <= p.grado; i++)

         p.coef[i] = -p.coef[i];

    return p;

    }


Polinomio & Polinomio::operator+(const Polinomio & p)

    {

    if (p.grado < grado)

       {

       for (int i = 0; i <= p.grado; i++)

                     coef[i] += p.coef[i];

       }

    else

          if (p.grado > grado)

             {

             double * c = new double[p.grado + 1];

             assert (c != 0);

                      int i = 0;

             for (; i <= grado; i++)

               c[i] = coef[i] + p.coef[i];

                      for (; i <= p.grado; i++)

                           c[i] = p.coef[i];

                      delete [] coef;

             coef = c;

                      grado = p.grado;

             }

         else

               {

            int i = grado;

            while (Cero(coef[i] + p.coef[i]) && (i >= 0))

                                  --i;

            if (i < 0) {

               delete [] coef;

                  grado = 0;

                  coef = new double[1];

                           coef[0] = 0.0;

               }

               else 

                  if (i == grado) {

                     for (int i = 0; i <= grado; i++)

                           coef[i] += p.coef[i];

                     }

                  else

                        {

                        grado = i;

                        double * c = new double[i + 1];

                                    assert (c != 0);

                       for (; i >= 0; i--)

                                         c[i] = coef[i] + p.coef[i];

                        delete [] coef;

                        coef = c;

                        }

                 }

    return *this;

    }


Polinomio & Polinomio::operator-(const Polinomio & p)

    {

    if (p.grado < grado)

       {

       for (int i = 0; i <= p.grado; i++)

            coef[i] -= p.coef[i];

       }

    else

          if (p.grado > grado)

             {

                      double * c = new double[p.grado + 1];

                      assert (c != 0);

             int i = 0;

                      for (; i <= grado; i++)

                           c[i] = coef[i] - p.coef[i];

                      for (; i <= p.grado; i++)

                           c[i] = -p.coef[i];

                      delete [] coef;

             coef = c;

             grado = p.grado;

             }

          else

                {

             int i = grado;

 while (Cero(coef[i] - p.coef[i]) && (i >= 0))

           --i;

                         if (i < 0)

                {

                            

                            grado = 0;

                            coef = new double[1];

                            coef[0] = 0.0;

                }

               else 

                               if (i == grado)

                                  for (int i = 0; i <= grado; i++)

             coef[i] -= p.coef[i];

                               else

             {

                        grado = i;

                                     double * c = new double[i + 1];

                                     assert (c != 0);

             for (; i >= 0; i--)

                c[i] = coef[i] - p.coef[i];

             

             coef = c;

                                     }

              }

    return *this;

    }


Polinomio & Polinomio::operator*(const Polinomio & p)

    {

    if (p.Nulo() || Nulo())

       {

       delete [] coef;

       coef = new double[1];

       assert(coef != 0);

       coef[0] = 0;

       grado = 0;

       }

   else

         {

         int nuevo_grado = grado + p.grado;

         double * c = new double[nuevo_grado + 1];

         assert(c != 0);

         for (int k = 0; k <= nuevo_grado; k++)

                        c[k] = 0.0;

         for (int j = p.grado; j >= 0; j--)

                       for (int i = grado; i >= 0; i--)

                             c[i+j] += p.coef[j] * coef[i];

         grado = nuevo_grado;

         delete [] coef;

         coef = c;

         }

    return *this;

    }


Polinomio & Polinomio::operator*(const double x)

    {

    if (Cero(x))

       {

       delete [] coef;

       coef = new double[1];

       coef[0] = 0;

       grado = 0;

       }

    else

          {

          for (int i = 0; i <= grado; i++)

                        coef[i] *= x;

          }

    return *this;

    }


Polinomio & operator*(double x, Polinomio & p)

    {

    if (Cero(x))

       {

       delete [] p.coef;

       p.coef = new double[1];

       p.coef[0] = 0;

       p.grado = 0;

       }

    else

          {

          for (int i = 0; i <= p.grado; i++)

                         p.coef[i] *= x;

          }

    return p;

    }


ostream & operator<<(ostream & s, const Polinomio & p)

    {

    if (p.Grado() > 1)

       {

       int i = p.Grado();

       s << p.Coef(i) << " x^" << i;

       for (i--; i > 1; i--)

                      if (!Cero(p.Coef(i)))

                         s << " + " << p.Coef(i) << "x^" << i;

       if (!Cero(p.Coef(1)))

          s << " + " << p.Coef(1)<< "x";

       if (!Cero(p.Coef(0)))

                   s << " + " << p.Coef(0);

       }

    else if (p.Grado() == 1)

              {

              s << p.Coef(1) << "x";

              if (!Cero(p.Coef(0)))

                          s << " + " << p.Coef(0);

              }

           else

                 s << p.Coef(0);

    return s;

    }

double Polinomio::evaluaGrado4(double t)
{
	return coef[4]*t*t*t*t+coef[3]*t*t*t+coef[2]*t*t+coef[1]*t+coef[0];
}

void Polinomio::sumCoef(int numcoef, double plus)
{
	coef[numcoef] = coef[numcoef] + plus;
}

 Polinomio::~Polinomio()
{

}

